#include "symbolTable.h"
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using namespace cp;

namespace{
struct VarInfo{
	std::string name;
	bool isConst;
	int value;
	VarInfo(const std::string _name, bool _isConst = false, int _value = 0):
		name(_name), isConst(_isConst),value(_value){}
};

std::vector<VarInfo> vars(1, VarInfo(""));
std::vector<std::map<std::string, int> > maps;
std::vector<cp::Quad> quads(1, cp::Quad(QuadOp::Error, 0));
}

namespace cp{
char* errMsg = new char[1024];
bool defineConst(const std::string& key, int value, int &id){
	if (maps.empty()) {
		sprintf(errMsg, "符号表栈为空");
		return false;
	}
	auto &map = *maps.rbegin();
	if (map.find(key) != map.end()){
		sprintf(errMsg, "已存在%s %s的定义",
			(vars[map[key]].isConst ? "常量" : "变量"),
			key.c_str());
		return false;
	}

	id = map[key] = vars.size();
	vars.push_back(VarInfo(key, true, value));
	return true;
}

bool declareVar(const std::string& key, int &id){
	if (maps.empty()) {
		sprintf(errMsg, "符号表栈为空");
		return false;
	}
	auto &map = *maps.rbegin();
	if (map.find(key) != map.end()){
		sprintf(errMsg, "已存在%s %s的定义",
			(vars[map[key]].isConst ? "常量" : "变量"),
			key.c_str());
		return false;
	}
	id = map[key] = vars.size();
	vars.push_back(VarInfo(key));
	return true;
}

int getTempID(){
	static int tempCt = 0;
	static char buf[256];
	sprintf(buf, "~T%d", ++tempCt);
	int ret;
	declareVar(buf, ret);
	return ret;
}

bool getVarID(const std::string& key, int &id){
	for (auto iter = maps.rbegin(); iter != maps.rend(); ++iter){
		auto iter1 = iter->find(key);
		if (iter1 == iter->end()) continue;
		id = iter1->second;
		return true;
	}
	sprintf(errMsg, "未找到符号%s", key.c_str());
	return false;
}

void pushTable(){
	maps.push_back(std::map<std::string,int>());
}

void popTable(){
	maps.pop_back();
}

int genQuad(int op, int resID, int leftID, int rightID){
	quads.push_back(Quad(op, resID, leftID, rightID));
	return quads.size()-1;
}

Quad &getQuad(int pos){
	return quads[pos];
}

void printQuads(FILE* fp){
	static const char* opNames[] = {
		"Error", ":=", ":=",
		"+", "-", "*", "/", "-", "+",
		"JMP", "J=", "J<>", "J>", "J>=", "J<", "J<="
	};
	static const bool isInt[][3] = {
		{0,0,0}, {1,1,0}, {0,1,0},
		{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, {0,1,0},
		{1,1,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1},
	};
	for (size_t i = 1; i < quads.size(); ++i){
		fprintf(fp, "(%d) %s", i, opNames[quads[i].op]);
		int id[3] = {quads[i].leftID, quads[i].rightID, quads[i].resID};
		for (int j = 0; j < 3; ++j){
			if (isInt[quads[i].op][j]) {fprintf(fp, " %d", id[j]); continue;}
			VarInfo &info = vars[id[j]];
			if (info.isConst) fprintf(fp, " %d", info.value);
			else fprintf(fp, " %s", info.name.c_str());
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "(%d) halt 0 0 0\n", quads.size());
}

}














